﻿#include "license.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <error.h>

License::License()
{

}




void License::rsa_init(void)
{
    printf("rsa init ... \n");
    OpenSSL_add_all_algorithms();
}

/*
*****************************************************************************************
*	函 数 名: rsa_sign
*	功能说明: RSA使用私钥签名
*	形    参:    pri_key     :   私钥
*               file_in     :   输入需要签名的文件
*               file_out    :   签名后生成的文件
*	返 回 值: 0：成功, 其他：失败
*****************************************************************************************
*/
int License::rsa_sign(const char *pri_key, const char *file_in, const char *file_out)
{
    int ret = -1;
    int keysize = 0;
    RSA *rsa = NULL;
    BIO *in = NULL, *out = NULL;
    unsigned char *rsa_in = NULL, *rsa_out = NULL;
    int rsa_inlen = 0, rsa_outlen = 0, len = 0;

    /* 从私钥提取 RSA */
    FILE *fp = fopen(pri_key, "r");
    if (NULL == fp) {
        perror("Open Key Error: \n");
        return -1;
    }

    rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL,NULL);
    if (!rsa) {
        perror("EVP_PKEY_get1_RSA Error: \n");
        goto error;
    }

    /* 打开file_in文件内容，创建file_out文件 */
    in = BIO_new_file(file_in, "rb");
    if (NULL == in) {
        printf("BIO_new_file: open source file fail\n");
        goto error;
    }

    out = BIO_new_file(file_out, "wb");
    if (NULL == out) {
        printf("BIO_new_file: open file_out file fail\n");
        goto error;
    }

    keysize = RSA_size(rsa);
    if (keysize < 0) {
        printf("RSA_size key size is %d\n", keysize);
        goto error;
    }

    rsa_in =(unsigned char *)OPENSSL_malloc(keysize * 2);
    if (rsa_in == NULL){
        perror("OPENSSL_malloc ras in fail\n");
        goto error;
    }

    rsa_out =(unsigned char *)OPENSSL_malloc(keysize);
    if (rsa_out == NULL){
        perror("OPENSSL_malloc ras out fail\n");
        goto error;
    }

    rsa_inlen = BIO_read(in, rsa_in, keysize * 2);
    if (rsa_inlen < 0) {
        perror("BIO_read Fail: \n");
        goto error;
    }

    /* 使用私钥验签，写入file_out文件 */
    len = RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, rsa, RSA_PKCS1_PADDING);
    if (len < 0) {
        perror("RSA_encrypt Fail: \n");
        goto error;
    }

    rsa_outlen = BIO_write(out, rsa_out, len);
    if (rsa_outlen < 0) {
        perror("BIO_write Fail: \n");
        goto error;
    }
    ret = 0;
    printf("sign success!\n");

error:
    if (NULL != fp) fclose(fp);
    if (rsa) RSA_free(rsa);
    if (in) BIO_free(in);
    if (out) BIO_free_all(out);
    if (rsa_in) OPENSSL_free(rsa_in);
    if (rsa_out) OPENSSL_free(rsa_out);

    return ret;
}

/*
*****************************************************************************************
*	函 数 名: rsa_verify
*	功能说明: RSA使用公钥验签
*	形    参:    pri_key     :   私钥
*               file_in     :   输入需要签名的文件
*               file_out    :   签名后生成的文件
*	返 回 值: 0：成功, 其他：失败
*****************************************************************************************
*/
int License::rsa_verify(const char *pri_key, const char *file_in,const char *file_out)
{
    int ret = ERR_NONE;
    int keysize = 0;
    RSA* rsa = NULL;
    BIO* in = NULL, *out = NULL;
    unsigned char* rsa_in = NULL, *rsa_out = NULL;
    int rsa_inlen = 0, rsa_outlen = 0, len = 0;

    /* 从公钥提取 RSA */
    FILE *fp = fopen(pri_key, "rb");
    if (NULL == fp) {
        perror("Open Key Error: \n");
        return -1;
    }

    if(NULL == (rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL,NULL)))
    {
        printf( "PEM_read_RSAPrivateKey error\n");
        fclose(fp);
        goto error;
    }

    /* 打开file_in文件内容，创建file_out文件 */
    in = BIO_new_file(file_in, "rb");
    if (NULL == in) {
        printf("BIO_new_file: open file_in file fail\n");
        ret = ERR_KEY_EN_OPEN;
        goto error;
    }

    out = BIO_new_file(file_out, "wb");
    if (NULL == out) {
        printf("BIO_new_file: open file_out file fail\n");
        ret = ERR_KEY_DE_OPEN;
        goto error;
    }

    keysize = RSA_size(rsa);
    if (keysize < 0) {
        printf("RSA_size key size is %d\n", keysize);
        ret = ERR_RSA_SIZE;
        goto error;
    }

    rsa_in = (unsigned char *)OPENSSL_malloc(keysize * 2);
    if (rsa_in == NULL){
        perror("OPENSSL_malloc ras in fail\n");
        ret = ERR_RSAIN_MALLOC;
        goto error;
    }
    rsa_out = (unsigned char *)OPENSSL_malloc(keysize);
    if (rsa_out == NULL) {
        perror("OPENSSL_malloc ras out fail\n");
        ret = ERR_RSAOUT_MALLOC;
        goto error;
    }

    // Read ENCYRPTED_FILE
    rsa_inlen = BIO_read(in, rsa_in, keysize * 2);
    if (rsa_inlen < 0) {
        perror("BIO_read Fail: \n");
        ret = ERR_KEY_EN_R;
        goto error;
    }

    /* 使用公钥验签，写入file_out文件 */
    len = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, rsa, RSA_PKCS1_PADDING);
    if (len < 0) {
        perror("Decrypt Fail: \n");
        ret = ERR_KEY_DE;
        goto error;
    }

    // Write DECRYPTED_FILE
    rsa_outlen = BIO_write(out, rsa_out, len);
    if (rsa_outlen < 0) {
        perror("BIO_write Fail: \n");
        ret = ERR_KEY_DE_W;
        goto error;
    }
    printf("verify success!\n");

error:
    if (NULL != fp) fclose(fp);
    if (rsa) RSA_free(rsa);
    if (in) BIO_free(in);
    if (out) BIO_free_all(out);
    if (rsa_in) OPENSSL_free(rsa_in);
    if (rsa_out) OPENSSL_free(rsa_out);

    return ret;
}
